home *** CD-ROM | disk | FTP | other *** search
- |
- | routines for saving/restoring user contexts
- |
- | long build_context(struct context *sav):
- | Called from an interrupt handler (such as the trap #1 routine
- | for system calls) saves the context of the interrupted
- | routine. Assumes that no user registers have been changed
- | since the interrupt, and that the PC and status register
- | are still on the stack. Returns the stack pointer being used
- | at the time of the interrupt **in register a1**.
- |
- | long save_context(struct context *sav):
- | Saves the context of the calling routine in the area pointed
- | to by sav. Save_context always returns 0 when initially called;
- | this is so processes can (by suitably manipulating the
- | saved registers) tell when the return from save_context is
- | actually caused by restoring the context, e.g.:
- | if (save_context(sav) == 0) { <<-- L1
- | /* do some stuff */
- | sav.regs[D0] = 1; /* for restore context */
- | restore_context(sav); /* goes back to L1 */
- | }
- | else /* this is the second time through */
- |
- | void restore_context(struct context *sav):
- | Restores a context previously saved by build_context or save_context.
- | Since the program counter is part of the context, this function
- | will never return (it's like longjmp()).
-
- .globl _build_context
- .globl _save_context
- .globl _restore_context
- .globl _fpu
- .globl _m68010
-
- _build_context:
- movel a0, sp@- | save a0; we'll use it for scratch
- movel sp@(8), a0 | get address of save area
- tstw _fpu | is there a real FPU in the system?
- beq nofpu | no -- we can skip the FPU save
- fsave a0@(78) | save internal state frame
- tstb a0@(78) | if NULL frame then FPU not in use
- beq nofpu
- fmovemx fp0-fp7,a0@(294) | save data registers
- fmoveml fpcr/fpsr/fpi,a0@(390) | and control registers
- nofpu:
- moveml d0-d7/a0-a6, a0@ | save registers D0-D7/A0-A6
- movel sp@(14), a0@(66) | save PC of context
- movew sp@(12), d0 | get SR of context
- movew d0, a0@(64) | save it
- tstw 0x59e | test longframe (AKP)
- beq short1 | short
- lea sp@(20), a1 | else long
- movew sp@(18), d1 | fetch frame format word
- movew d1, a0@(402) | stash it away for later
- tstw _m68010 | are we running on a 68010?
- bne short2 | yes -- definitely a simple interrupt frame
- |
- | note: in order to have got to this point in the code we must be
- | running on an 020/030
- |
- bftst d1{#16:#4} | is it the simple interrupt frame?
- beq short2 | yes -- just dump the stack contents
- moveml a1@+, d1-d3 | get instruction address/4 internal words
- moveml d1-d3, a0@(404) | save them
- bra short2
- short1:
- lea sp@(18), a1 | save supervisor stack pointer
- short2: | note that it should be pointing above the PC
- movel a1, a0@(70)
- movel usp, a1 | save user stack pointer
- movel a1, a0@(60)
- btst #13, d0 | check for supervisor mode
- beq L_CONT1 | user mode; we already have stack in a1
- L_SUPER1:
- | note: this was lea a0@(18), but moving from the save state buffer
- | means not testing longframe again. (AKP)
- movel a0@(70), a1 | was using super stack pointer before interrupt
- |
- L_CONT1:
- movel 0x408, a0@(74) | save GEMDOS terminate vector
- movel sp@+, a0@(32) | save old register a0
- rts
-
- _save_context:
- movel a0, sp@- | save a0
- movel sp@(8), a0 | get address of context save area
-
- | if running with a true coprocessor we need to save the FPU state
-
- tstw _fpu | is there a true FPU in the system
- beq nofpu2
- fsave a0@(78) | save internal state frame
- tstb a0@(78) | if NULL frame then the FPU is not in use
- beq nofpu2 | skip programmer's model save
- fmovemx fp0-fp7,a0@(294) | save data registers
- fmoveml fpcr/fpsr/fpi,a0@(390) | and control registers
- nofpu2:
- | AGK: I am somewhat unsure of this assumption, viz that save_context
- | can never be called in a situation where a co-processor
- | mid-instruction stack frame would be required. I suspect this is a
- | valid assumption, in which case the above FPU code is redundant, the
- | next line is not however!
-
- clrw a0@(402) | mark as a 4 word stack frame
-
- moveml d0-d7/a0-a6, a0@ | save D0-D7/A0-A6
- lea sp@(8), a1
- movel a1, a0@(70) | save supervisor stack pointer
- | note that it should be pointing above the PC
- movel a1@(-4), a0@(66) | save PC
- movel usp, a1
- movel a1, a0@(60) | save user stack pointer
- movew sr, d0
- movew d0, a0@(64) | save status register
- movel 0x408, a0@(74) | save GEMDOS terminate vector
- movel sp@+, a0@(32) | save old a0
- moveql #0, d0 | return 0
- rts
-
- _restore_context:
- orw #0x0700, sr | mask interrupts
- movel sp@(4), a0 | address of context save area
- movel a0@(70), sp | supervisor stack pointer
- movel a0@(60), a1
- movel a1, usp | set user stack pointer
- movel a0@(74), 0x408 | restore GEMDOS terminate vector
-
- tstw 0x59e | test longframe (AKP)
- beq short3
-
- movew a0@(402),d0 | fetch frame format word
- tstw _m68010 | are we on a 68010?
- bne just0 | yes, so it's a simple interrupt frame
-
- bftst d0{#16:#4} | is it the simple interrupt frame ?
- beq just0 | yes so just push a zero
- moveml a0@(404),d1-d3 | saved instruction address/4 internal words
- moveml d1-d3,sp@-
- just0: movew d0,sp@-
-
- short3:
- movel a0@(66), sp@- | push the PC
- movew a0@(64), d0 | get status register
- movew d0, sp@- | push the status register
-
- | if running with a true co-processor we need to restore the FPU state
-
- tstw _fpu
- beq nofpu3
- tstb a0@(78) | if NULL frame then FPU not in use
- beq short7 | skip programmer's model restore
- fmoveml a0@(390), fpcr/fpsr/fpi | restore control registers
- fmovemx a0@(294), fp0-fp7 | and data registers
- short7: frestore a0@(78) | finally the internal state
-
- nofpu3:
- moveml a0@, d0-d7/a0-a6 | restore registers d0-d7/a0-a6
- rte | jump back to old context
-
-